<?php

/*
 * This is my (jas) attempt at making an object model for challenges.
 * My idea at the moment is that this thing will be created and will remain a challenge
 * until accepted by both players at which point it becomes a game set... I guess
 *
 */
class challenge_object extends CI_Model{

	public $PLAYER1, $PLAYER2, $MAP_BAN, $STATUS, $NUM_GAMES, $GAMES_PLAYED, $GAME_TYPE, $PLAYER1_WINS, $PLAYER2_WINS, $WINNER, $DATE_ISSUED;
	private $ID, $DATE_COMPLETE;

	private $SETS_TABLE = 'game_sets';
	private $GAMES_TABLE = 'games';

	//Creates empty challenge object. Used for method access and by load->model I think
	function __construct($data = array()){
		$this->load->model('game_model');

		if(count($data) > 0){
			if(isset($data['game_set_id'])) $this->ID = $data['game_set_id'];
			else $this->ID = -1;

			if(isset($data['date_issued'])) $this->DATE_ISSUED = $data['date_issued'];
			else $this->DATE_ISSUED = time();

			if(isset($data['date_complete'])) $this->DATE_COMPLETE = $data['date_complete'];
			else $this->DATE_COMPLETE = NULL;

			if(isset($data['player1'])) $this->PLAYER1 = $data['player1'];
			else $this->PLAYER1 = '';

			if(isset($data['player2'])) $this->PLAYER2 = $data['player2'];
			else $this->PLAYER2 = '';

			if(isset($data['map_ban'])) $this->MAP_BAN = $data['map_ban'];
			else $this->MAP_BAN = '';

			if(isset($data['status'])) $this->STATUS = $data['status'];
			else $this->STATUS = 'pending';

			if(isset($data['number_games'])) $this->NUM_GAMES = $data['number_games'];
			else $this->NUM_GAMES = 3;

			if(isset($data['games_played'])) $this->GAMES_PLAYED = $data['games_played'];
			else $this->GAMES_PLAYED = 0;

			if(isset($data['game_type'])) $this->GAME_TYPE = $data['game_type'];
			else $this->GAME_TYPE = 'ladder';

			if(isset($data['player1_wins'])) $this->PLAYER1_WINS = $data['player1_wins'];
			else $this->PLAYER1_WINS = 0;

			if(isset($data['player2_wins'])) $this->PLAYER2_WINS = $data['player2_wins'];
			else $this->PLAYER2_WINS = 0;

			if(isset($data['winner'])) $this->WINNER = $data['winner'];
			else $this->WINNER = '';
		}
	}

	function get_id(){
		return $this->ID;
	}

	function get_issued_date(){
		return $DATE_ISSUED;
	}

	//TODO: Create
	function get_deadline_date(){
		return '';
	}

	//"Static" method used to check if a challenge is valid
	function is_valid_challenge($challenger, $victim){
		$this->load->model('ladder_model');
		$targets = $this->ladder_model->get_challenge_list($challenger);
		$valid = false;

		$current_challenges = $this->load_user_challenge($challenger);

		//Check if target is valid
		foreach($targets as $row) {
			if($row['account'] == $victim) {
				$valid = true;
				break;
			}
		}

		//Check if any existing challenges already exist
		if (count($current_challenges) > 0){
			foreach ($current_challenges as $row){
				if ($row->PLAYER1 == $victim || $row->PLAYER2 == $victim){
					$valid = false;
					break;
				}
			}
		}

		return $valid;
	}

	//Create sql array from object data for commiting back to database
	function get_sql_array(){
		$commit_array = array(
			'player1' => $this->PLAYER1,
			'player2' => $this->PLAYER2,
			'map_ban' => $this->MAP_BAN,
			'status' => $this->STATUS,
			'number_games' => $this->NUM_GAMES,
			'games_played' => $this->GAMES_PLAYED,
			'game_type' => $this->GAME_TYPE,
			'player1_wins' => $this->PLAYER1_WINS,
			'player2_wins' => $this->PLAYER2_WINS,
			'winner' => $this->WINNER
		);

		return $commit_array;
	}

	//Updates database entry with object values. Would be used to accept a challenge
	private function update_challenge(){
		if(!empty($this->ID)){
			$this->db->where('game_set_id', $this->ID);
			return $this->db->update($this->SETS_TABLE, $this->get_sql_array());
		}
	}

	private function record_finish_time(){
		$date = date('Y-m-d');
		return $this->db->query('UPDATE ' . $this->SETS_TABLE . ' SET date_complete =' .$date .'WHERE game_set_id = ' . $this->ID);
	}

	/**
	 * Creates a new challenge in the database.
	 * This includes creating the game set to be played based on the given info,
	 * but not the individual games.  @See create_game handles the creation of these individual games.
	 * Data has been already validated by the controller.
	 *
	 * @param $data - Initial Game set information passed by the challenge form
	 *      Includes:
	 *	      Players playing, number of players (def: 2), game_type (laddder / casual), number of games, etc.
	 *@return ID of the created game set or null in the case of an error
	 *
	 */
	function create_challenge ($data){
		//If challenge is valid, commit to database
		if(!empty($data['player1']) && !empty($data['player2']) && $this->is_valid_challenge($data['player1'], $data['player2'])){
			$this->db->insert($this->SETS_TABLE, $data);
			$data['game_set_id'] = $this->db->insert_id();

			if (mysql_error() != '') $inserted = NULL;
			else $inserted = new challenge_object($data);
		} else {
			$inserted = null;
		}

		return $inserted;
	}

	//Checks if the current challenge can be accepted, and if so, accepts it.
	function accept_challenge($decision){
		if($this->STATUS == 'pending'){
			$this->STATUS = $decision ? 'ongoing' : 'declined';
			$this->update_challenge();
		}
		else return false;
	}

	//Used to report a game for this challenge
	function report_game($input){
		$this->load->model('profile_model');
		//Confirm that game is ongoing
		if($this->STATUS == 'ongoing'){
			$this->GAMES_PLAYED++;

			//Add wins
			if($this->PLAYER1 == $input['winner']) {
				$total_wins = ++$this->PLAYER1_WINS;
				$winner = $this->PLAYER1;
				$loser = $this->PLAYER2;
			}
			else {
				$total_wins = ++$this->PLAYER2_WINS;
				$winner = $this->PLAYER2;
				$loser = $this->PLAYER1;
			}

			//Check if the challenge is complete
			if($total_wins > ($this->NUM_GAMES/2)) {
				$this->STATUS = 'finished';
				$this->record_finish_time();
				$this->WINNER = $winner;
				$this->profile_model->update_score($winner, $loser);
			}

			//if there is a file to upload
			if(isset($_FILES['replay']) && $_FILES['replay']['size'] > 0){

				//get file info from php auto constants
				$fileName = $_FILES['replay']['name'];
				$tmpName  = $_FILES['replay']['tmp_name'];
				$fileSize = $_FILES['replay']['size'];
				$fileType = $_FILES['replay']['type'];
				//open file and read into memory
				$fp      = fopen($tmpName, 'r');
				$content = fread($fp, filesize($tmpName));
				fclose($fp);

				//add replay data to input array for database
				$input['name'] = $fileName;
				$input['replay'] = $content;
				$input['size'] = $fileSize;
				$input['type'] = $fileType;
			}
			//Commit changes to game_sets table. Add game to games table.
			$error = $this->db_add_game($input);
			if (!isset($error)){
				$this->update_challenge();
			} else {
				return $error;
			}
		}
		else return false;
	}

	private function db_add_game($input){
		//one day we should rename the set_number field to games_played
		$sql = "INSERT INTO " .$this->GAMES_TABLE ." (set_number, map, game_set_id, winner, replay, name, size, type, date)
		VALUES (?, ?, ?, ?, ?, ?, ?, ?, now())";
		$bindings = array(
			$this->GAMES_PLAYED,
			$input['map'],
			$input['game_set_id'],
			$input['winner'],
			$input['replay'],
			$input['name'],
			$input['size'],
			$input['type']
		);
		$this->db->query($sql, $bindings);
		
		if (mysql_error() != ''){
			return mysql_error();
		}
	}

	//Loads challenge with specified id from database
	function load_challenge($id){
		if(empty($id)) return NULL;

		$this->db->where('game_set_id', $id);
		$query = $this->db->get($this->SETS_TABLE);

		$challenge = NULL;

		if(!empty($query)){
			$results = $query->result_array();
			$challenge = new challenge_object($results[0]);
		}

		return $challenge;
	}

	//Loads challenge for a person
	function load_user_challenge($account){
		if(empty($account)) return NULL;

		$query_str = "SELECT * FROM " . $this->SETS_TABLE . " WHERE (player1='" . $account .
				     "' OR player2='" . $account . "') AND (status='pending' OR status='ongoing')";
		$query = $this->db->query($query_str);

		$challenge_list = array();
		if(!empty($query)){
			$results = $query->result_array();
			for($i = 0; $i < count($results); $i++){
				$challenge_list[$i] = new challenge_object($results[$i]);
			}
		}
		return $challenge_list;
	}
}
